package practise.mulitThreads.ChefAndWaiter;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by richard on 4/27/14.
 */
public class Resturant {
    private BlockingQueue<Order> orders = new LinkedBlockingDeque<Order>();
    private BlockingQueue<Chef> chefs = new LinkedBlockingDeque<Chef>();
    private BlockingQueue<Waiter> waiters = new LinkedBlockingDeque<Waiter>();
    private BlockingQueue<Customer> customers = new LinkedBlockingDeque<Customer>();
    private BlockingQueue<Dinner> dinners = new LinkedBlockingDeque<Dinner>();
    ReentrantLock orderLock = new ReentrantLock();
    ReentrantLock waiterLock = new ReentrantLock();
    ReentrantLock chefLock = new ReentrantLock();

    private static volatile int dishNumber = 0;

    public Order getOrderAndCook(Chef chef) throws InterruptedException {

        try {
            orderLock.lock();

            if (getOrders().isEmpty()) {
                chef.wait();
            }
        } finally {
            orderLock.unlock();
        }


        return getOrders().take();
    }

    public Waiter callAWaiter(Customer customer) throws InterruptedException {
        try {
            waiterLock.lock();
            if (getWaiters().isEmpty()) {
                customer.wait();
            }
        } finally {
            waiterLock.unlock();
        }
        Order order = new Order();
        order.setDishName("DishName" + dishNumber);
        order.setCustomerName(customer.getName());
        getOrders().add(order);
        return getWaiters().take();
    }

    public Dinner deliverADinner(Waiter waiter) throws InterruptedException {

        return getDinners().take();
    }


    public BlockingQueue<Order> getOrders() {
        return orders;
    }

    public void setOrders(BlockingQueue<Order> orders) {
        this.orders = orders;
    }

    public BlockingQueue<Chef> getChefs() {
        return chefs;
    }

    public void setChefs(BlockingQueue<Chef> chefs) {
        this.chefs = chefs;
    }

    public BlockingQueue<Waiter> getWaiters() {
        return waiters;
    }

    public void setWaiters(BlockingQueue<Waiter> waiters) {
        this.waiters = waiters;
    }

    public BlockingQueue<Customer> getCustomers() {
        return customers;
    }

    public void setCustomers(BlockingQueue<Customer> customers) {
        this.customers = customers;
    }

    public BlockingQueue<Dinner> getDinners() {
        return dinners;
    }

    public void setDinners(BlockingQueue<Dinner> dinners) {
        this.dinners = dinners;
    }
}
